﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Diagnostics.Contracts;

namespace ShredTheLog.Api
{
    [ContractClass(typeof(Theme_Contract))]
    public interface ITheme
    {
        string ID { get; }
        string Name { get; }
        ThemeSmiley[] Smileys { get; }
        ThemeSound[] Sounds { get; }
    }

    [ContractClassFor(typeof(ITheme))]
    internal abstract class Theme_Contract : ITheme
    {
        string ITheme.ID
        {
            get
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException();
            }
        }

        string ITheme.Name
        {
            get
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException();
            }
        }

        ThemeSmiley[] ITheme.Smileys
        {
            get 
            {
                Contract.Ensures(Contract.Result<ThemeSmiley[]>() != null);
                throw new NotImplementedException(); 
            }
        }


        ThemeSound[] ITheme.Sounds
        {
            get 
            {
                Contract.Ensures(Contract.Result<ThemeSound[]>() != null);
                throw new NotImplementedException(); 
            }
        }
    }

    [ContractClass(typeof(SkinPart_Contract))]
    public interface ISkinPart
    {
        string ThemeID { get; }
        string PartID { get; }
        Uri PartUri { get; }
    }

    [ContractClassFor(typeof(ISkinPart))]
    internal abstract class SkinPart_Contract : ISkinPart
    {
        string ISkinPart.ThemeID
        {
            get
            {
                Contract.Ensures(Contract.Result<string>() == null || !String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException();
            }
        }

        string ISkinPart.PartID
        {
            get
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException();
            }
        }

        Uri ISkinPart.PartUri
        {
            get 
            {
                Contract.Ensures(Contract.Result<Uri>() != null);
                throw new NotImplementedException(); 
            }
        }
    }

    public sealed class ThemeSmiley
    {
        [ContractInvariantMethod]
        void ObjectInvariant()
        {
            Contract.Invariant(!String.IsNullOrWhiteSpace(SmileyDefinitionId));
            Contract.Invariant(SmileyFactory != null);
        }

        public string SmileyDefinitionId { get; private set; }
        public Func<string, Inline> SmileyFactory { get; private set; }
        
        public ThemeSmiley(string smileyDefinitionID, Func<string, Inline> smileyFactory)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(smileyDefinitionID));
            Contract.Requires(smileyFactory != null);

            SmileyDefinitionId = smileyDefinitionID;
            SmileyFactory = smileyFactory;
        }
    }

    [ContractClass(typeof(SmileyDefinition_Contract))]
    public interface ISmileyDefinition
    {
        string ID { get; }
        string[] Patterns { get; }
    }

    [ContractClassFor(typeof(ISmileyDefinition))]
    internal abstract class SmileyDefinition_Contract : ISmileyDefinition
    {
        string ISmileyDefinition.ID
        {
            get
            {
                Contract.Ensures(!String.IsNullOrWhiteSpace(Contract.Result<string>()));
                throw new NotImplementedException();
            }
        }

        string[] ISmileyDefinition.Patterns
        {
            get 
            {
                Contract.Ensures(Contract.Result<string[]>() != null);
                throw new NotImplementedException(); 
            }
        }
    }

    public sealed class ThemeSound
    {
        public Type NotificationType { get; private set; }
        public Uri SoundUri{ get; private set; }
        
        public ThemeSound(Type notificationType, Uri soundUri)
        {
            Contract.Requires(notificationType != null);
            Contract.Requires(soundUri != null);

            NotificationType = notificationType;
            SoundUri = soundUri;
        }
    }
}
